﻿using OpenTK.Graphics;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using LightCAD.Three;
using EventArgs = System.EventArgs;
using OpenTK;
using LightCAD.Three.OpenGL;
using LightCAD.MathLib;
using System.Runtime.InteropServices;
using System.Security;
using LightCAD.MathLib.CSG;
using Matrix4 = LightCAD.MathLib.Matrix4;
using LightCAD.MathLib.Csg;
using SkiaSharp;
using System.Diagnostics;
using Net3dBool;
using Vector2 = LightCAD.MathLib.Vector2;

namespace CSG_TEST
{
    public partial class MainForm : Form
    {
        private GLControl glControl;
        private WebGLRenderer renderer;
        private PerspectiveCamera camera;
        private Scene scene;
        private Group model;
        private BoxGeometry geometry;
        private RenderCanvas canvas;
        private OrbitControls controls;
        public MainForm()
        {
            InitializeComponent();
            this.glControl = new GLControl();

            this.glControl.VSync = false;
            this.Controls.Add(this.glControl);
            this.glControl.Dock = DockStyle.Fill;
            this.Load += ThreeTestForm_Load;
            this.Closing += ThreeTestForm_Closing; ;
            this.WindowState = FormWindowState.Maximized;
            //glControl.Run();
            this.txtInfo.BringToFront();
            Application.Idle += Application_Idle;
        }
        private bool isLoad = false;
        //V3.V(SuppressUnmanagedCodeSecurity]
        //V3.V(DllImport("OPENGL32.DLL", EntryPoint = "wglGetProcAddress", ExactSpelling = true, SetLastError = true)]
        //internal extern static IntPtr GetProcAddress(String lpszProc);
        [SuppressUnmanagedCodeSecurity]
        [DllImport("OPENGL32.DLL", EntryPoint = "wglGetProcAddress", ExactSpelling = true, SetLastError = true)]
        internal extern static IntPtr GetProcAddress(IntPtr lpszProc);

        private void ThreeTestForm_Load(object? sender, EventArgs e)
        {
            var context = GraphicsContext.CurrentContext;
            gl.GetAddressFunc = (fn) =>
            {
                var context_internal = context as IGraphicsContextInternal;
                var ptr = context_internal.GetAddress(fn);
                return ptr;
            };


            init();
            Resize();
            this.SizeChanged += ThreeTestForm_SizeChanged;
            isLoad = true;

        }
        private void init()
        {
            this.scene = new Scene();
            var ambientLight = new AmbientLight(0xcccccc, 0.4);
            scene.add(ambientLight);

            var dirLight = new DirectionalLight(0xffffff, 0.8);
            dirLight.position.Set(1, 2, 3);
            scene.add(dirLight);

            this.geometry = new BoxGeometry(200, 200, 200);
            //var material = new MeshBasicMaterial(new MaterialValues { color = new LightCAD.Three.Color(0xff0000) });
            var material = new MeshPhongMaterial { color = new Color(0xff0000), side = LightCAD.MathLib.Constants.DoubleSide };//map = map,

            //var mesh = new LightCAD.Three.Mesh(geometry, material);
            //this.scene.add(mesh);

            this.model = new Group();
            this.scene.add(this.model);

            var ratio = glControl.Width / glControl.Height;
            camera = new PerspectiveCamera(70, ratio, 0.1, 1000);
            camera.position.Z = 300;

            this.canvas = new RenderCanvas().Set(glControl.Width, glControl.Height);
            this.renderer = new WebGLRenderer(canvas);
            //renderer.setSize(glControl.Width, glControl.Height);
            controls = new OrbitControls(camera, glControl);
            controls.screenSpacePanning = true;


            materialA = new MeshPhongMaterial { color = new Color(0xFF0000) };
            materialB = new MeshPhongMaterial { color = new Color(0x00FF00) };
            matResult = new MeshPhongMaterial { color = new Color(0x0000FF) };

            this.cboGeo.SelectedIndex = 0;
            this.cboCSG.SelectedIndex = 0;

        }
        private void Application_Idle(object? sender, EventArgs e)
        {
            this.glControl.MakeCurrent();
            Animate();
            this.glControl.SwapBuffers();
        }
        private void Animate()
        {
            if (!isLoad)
                return;
            this.renderer.setClearColor(0x000000);
            this.renderer.render(this.scene, camera);
        }

        private void ThreeTestForm_SizeChanged(object? sender, EventArgs e)
        {
            Resize();
        }
        private void Resize()
        {
            this.camera.aspect = this.Width / (float)this.Height;
            camera.updateProjectionMatrix();
            glControl.Width = this.Width;
            glControl.Height = this.Height;
            this.canvas.Set(glControl.Width, glControl.Height);
            this.renderer.setViewport(0, 0, glControl.Width, glControl.Height);
        }

        private void ThreeTestForm_Closing(object? sender, CancelEventArgs e)
        {
        }
        private void MainForm_Load(object sender, EventArgs e)
        {
        }

        private BufferGeometry geometryA;
        private BufferGeometry geometryB;
        private BufferGeometry csgResult;
        private MeshPhongMaterial materialA;
        private MeshPhongMaterial materialB;
        private MeshPhongMaterial matResult;
        private void loadModel()
        {


            //var path = @"D:\Study\2d-study\LightCAD\Gitee-LightCAD2\Cork\samples\";
            //ballA = OffFile.Read($"{path}ballA.off");
            //ballB = OffFile.Read($"{path}ballB.off");
            //ballResult = OffFile.Read($"{path}result.off");
            //ShowRawMesh(ballA, 0xFF0000);
            //ShowRawMesh(ballB, 0x00FF00);
            //ShowRawMesh(ballResult);
        }

        string[] csgGeoNames = new string[]{
       "1-球与球-分片10",
       "2-球与球-分片50",
       "3-球与立方体-分片10",
       "4-球与立方体-分片50",
       "5-长方体与立方体-分片10",
       "6-长方体与立方体-分片50" };

        private void cboGeo_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.model.clear();
            var transMatrix = new Matrix4().MakeTranslation(100, 0, 0);
            var index = (cboGeo.SelectedItem as String).Substring(0, 1);
            if (this.geometryA != null)
            {
                this.geometryA.dispose();
                this.geometryB.dispose();
            }
            if (this.csgResult != null)
            {
                this.csgResult.dispose();
            }

            switch (index)
            {
                case "1":
                    geometryA = new SphereGeometry(100, 10, 10);
                    geometryB = new SphereGeometry(100, 10, 10).applyMatrix4(transMatrix);
                    break;
                case "2":
                    geometryA = new SphereGeometry(100, 50, 50);
                    geometryB = new SphereGeometry(100, 50, 50).applyMatrix4(transMatrix);
                    break;
                case "3":
                    geometryA = new SphereGeometry(100, 10, 10);
                    geometryB = new BoxGeometry(150, 150, 150, 10, 10, 10);
                    break;
                case "4":
                    geometryA = new SphereGeometry(100, 50, 50);
                    geometryB = new BoxGeometry(150, 150, 150, 50, 50, 50);
                    break;
                case "5":
                    geometryA = new BoxGeometry(200, 40, 100, 10, 10, 10).applyMatrix4(transMatrix);
                    geometryB = new BoxGeometry(100, 100, 100, 10, 10, 10);
                    break;
                case "6":
                    geometryA = new BoxGeometry(200, 40, 100, 50, 50, 50).applyMatrix4(transMatrix);
                    geometryB = new BoxGeometry(100, 100, 100, 50, 50, 50);
                    break;

            }

            var meshA = new Mesh(this.geometryA, this.materialA);
            var meshB = new Mesh(this.geometryB, this.materialB);
            this.model.add(meshA);
            this.model.add(meshB);
        }



        private void ShowRawMesh(RawMesh rawMesh, int color = 0x808080)
        {
            var material = new MeshPhongMaterial
            {
                color = new Color(color),
                side = LightCAD.MathLib.Constants.DoubleSide
            };//map = map,
            var geometry = new BufferGeometry();
            var posList = new List<double>();
            foreach (var v in rawMesh.vertices)
            {
                posList.Add(v.pos.x);
                posList.Add(v.pos.y);
                posList.Add(v.pos.z);
            }
            geometry.setAttribute("position", new Float32BufferAttribute(posList.ToArray(), 3));

            var idxList = new List<int>();
            foreach (var t in rawMesh.triangles)
            {
                idxList.Add(t.a);
                idxList.Add(t.b);
                idxList.Add(t.c);
            }
            geometry.setIndex(idxList.ToArray());
            geometry.computeVertexNormals();
            var mesh = new LightCAD.Three.Mesh(geometry, material);
            this.model.add(mesh);
        }
        private Button curActionButton;
        private void SelectButton(Button button)
        {
            if (this.curActionButton != null)
            {
                this.curActionButton.BackColor = this.BackColor;
            }
            this.curActionButton = button;
            this.curActionButton.BackColor = System.Drawing.Color.AliceBlue;

        }
        private void btnUnion_Click(object sender, EventArgs e)
        {
            SelectButton(sender as Button);
            BoolOperate(cboCSG.SelectedItem as string, "Union");
        }



        private void btnDiff_Click(object sender, EventArgs e)
        {
            SelectButton(sender as Button);
            BoolOperate(cboCSG.SelectedItem as string, "Diff");
        }

        private void btnIsct_Click(object sender, EventArgs e)
        {
            SelectButton(sender as Button);
            BoolOperate(cboCSG.SelectedItem as string, "Isct");
        }

        private void btnXOR_Click(object sender, EventArgs e)
        {
            SelectButton(sender as Button);
            BoolOperate(cboCSG.SelectedItem as string, "XOR");
        }
        private void ShowResult(DateTime start)
        {
            var delta = DateTime.Now - start;

            this.model.clear();
            var resultMesh = new Mesh(this.csgResult, this.matResult);
            this.model.add(resultMesh);

            var index = (cboGeo.SelectedItem as String).Substring(0, 1);
            var csgName = csgGeoNames[int.Parse(index) - 1];
            var opName = curActionButton.Name.Substring(3);
            txtInfo.AppendText(
                $"{csgName} - {opName}\n" +
                $"geometryA:{geometryA.getIndex().count / 3}\n" +
                $"geometryB:{geometryB.getIndex().count / 3}\n" +
                $"csgResult:{csgResult.getIndex().count / 3}\n" +
                $"spendtime:{delta.TotalSeconds}s\n\n"); ;

        }
        private void BoolOperate(string csgMethod, string op)
        {
            var st = DateTime.Now;
            if (csgMethod == "Cork")
            {
                var corkA = GeometryToCork(this.geometryA);
                var corkB = GeometryToCork(this.geometryB);
                RawMesh result = null;

                if (op == "Union")
                    Cork.computeUnion(corkA, corkB, out result);
                else if (op == "Diff")
                    Cork.computeDifference(corkA, corkB, out result);
                else if (op == "Isct")
                    Cork.computeIntersection(corkA, corkB, out result);
                else if (op == "XOR")
                    Cork.computeSymmetricDifference(corkA, corkB, out result);
                else
                    throw new Exception($"error op {op}");

                this.csgResult = CorkToGeometry(result);
                ShowResult(st);
            }
            else if (csgMethod == "CSG")
            {
                var csgA = GeometryToCsg(this.geometryA);
                var csgB = GeometryToCsg(this.geometryB);
                CsgSolid result = null;

                if (op == "Union")
                    result = csgA.Union(csgB);
                else if (op == "Diff")
                    result = csgA.Substract(csgB);
                else if (op == "Isct")
                    result = csgA.Intersect(csgB);
                else if (op == "XOR")
                {
                    MessageBox.Show($"not support xor");
                    return;
                }
                else
                {
                    MessageBox.Show($"error op {op}");
                    return;
                }
                this.csgResult = CsgToGeometry(result);
                ShowResult(st);

            }
            else if (csgMethod == "NetBool")
            {
                var nblA = GeometryToNbl(this.geometryA);
                var nblB = GeometryToNbl(this.geometryB);
                NblSolid result = null;
                var modeler = new BoolModeler(nblA, nblB);


                if (op == "Union")
                    result = modeler.GetUnion();
                else if (op == "Diff")
                    result = modeler.GetDifference();
                else if (op == "Isct")
                    result = modeler.GetIntersection();
                else if (op == "XOR")
                {
                    MessageBox.Show($"not support xor");
                    return;
                }
                else
                {
                    MessageBox.Show($"error op {op}");
                    return;
                }
                this.csgResult = NblToGeometry(result);
                ShowResult(st);
            }
        }

        private BufferGeometry NblToGeometry(NblSolid solid)
        {
            var geometry = new BufferGeometry();
            var posList = new List<double>();
            foreach (var v in solid.GetVertices())
            {
                posList.Add(v.X);
                posList.Add(v.Y);
                posList.Add(v.Z);
            }
            geometry.setAttribute("position", new Float32BufferAttribute(posList.ToArray(), 3));

            var idxList = new List<int>();
            idxList.AddRange(solid.GetIndices());   
            geometry.setIndex(idxList.ToArray());
            geometry.computeVertexNormals();
            return geometry;
        }

        private NblSolid GeometryToNbl(BufferGeometry geo)
        {
            var vertices = new List<NblVec3>();
            var posArr = geo.getAttribute("position").array;
            for (var i = 0; i < posArr.Length; i += 3)
            {
                var vert = new NblVec3(posArr[i], posArr[i + 1], posArr[i + 2]);
                vertices.Add(vert);
            }
            var idxArr = geo.getIndex().intArray;
            var indices = new List<int>();
            for (var i = 0; i < idxArr.Length; i += 3)
            {
                indices.AddRange(new int[] { idxArr[i], idxArr[i + 1], idxArr[i + 2] });
            }
            return new NblSolid(vertices.ToArray(), indices.ToArray());
        }

        private RawMesh GeometryToCork(BufferGeometry geo)
        {
            var rawMesh = new RawMesh();
            var posArr = geo.getAttribute("position").array;
            for (var i = 0; i < posArr.Length; i += 3)
            {
                var corkVert = new CorkVertex(posArr[i], posArr[i + 1], posArr[i + 2]);
                rawMesh.vertices.Add(corkVert);
            }
            var idxArr = geo.getIndex().intArray;
            for (var i = 0; i < idxArr.Length; i += 3)
            {
                var corkTri = new CorkTriangle(idxArr[i], idxArr[i + 1], idxArr[i + 2]);
                rawMesh.triangles.Add(corkTri);
            }
            return rawMesh;
        }
        private BufferGeometry CorkToGeometry(RawMesh rawMesh)
        {
            var geometry = new BufferGeometry();
            var posList = new List<double>();
            foreach (var v in rawMesh.vertices)
            {
                posList.Add(v.pos.x);
                posList.Add(v.pos.y);
                posList.Add(v.pos.z);
            }
            geometry.setAttribute("position", new Float32BufferAttribute(posList.ToArray(), 3));

            var idxList = new List<int>();
            foreach (var t in rawMesh.triangles)
            {
                idxList.Add(t.a);
                idxList.Add(t.b);
                idxList.Add(t.c);
            }
            geometry.setIndex(idxList.ToArray());
            geometry.computeVertexNormals();
            return geometry;
        }



        public static CsgSolid GeometryToCsg(BufferGeometry geometry)
        {
            var csg = new CsgSolid();
            var polygons = new List<CsgPolygon>();

            var indices = geometry.index != null ? geometry.index.intArray : null;
            var attributes = geometry.attributes;

            var positions = (double[])attributes["position"].array;
            //var colors = (double[])(attributes.get("color") != null ? attributes["color"].array : null);

            if (indices == null)
            {
                for (int i = 0; i < positions.Length; i += 9)
                {
                    var poly = new CsgPolygon(
                        new CsgVertex(new CsgVec3(positions[i], positions[i + 1], positions[i + 2]), default(Vector2D)),
                        new CsgVertex(new CsgVec3(positions[i + 3], positions[i + 4], positions[i + 5]), default(Vector2D)),
                        new CsgVertex(new CsgVec3(positions[i + 6], positions[i + 7], positions[i + 8]), default(Vector2D)));
                    polygons.Add(poly);
                }
            }
            else
            {
                for (var i = 0; i < indices.Length; i += 3)
                {
                    var i0 = indices[i] * 3;
                    var i1 = indices[i + 1] * 3;
                    var i2 = indices[i + 2] * 3;
                    var poly = new CsgPolygon(
                        new CsgVertex(new CsgVec3(positions[i0], positions[i0 + 1], positions[i0 + 2]), default(Vector2D)),
                        new CsgVertex(new CsgVec3(positions[i1], positions[i1 + 1], positions[i1 + 2]), default(Vector2D)),
                        new CsgVertex(new CsgVec3(positions[i2], positions[i2 + 1], positions[i2 + 2]), default(Vector2D)));
                    polygons.Add(poly);

                }
            }
            csg.Polygons = polygons;
            return csg;
        }
        public BufferGeometry CsgToGeometry(CsgSolid csg)
        {
            var geometry = new BufferGeometry();

            var vertices = new List<double>();
            var indices = new List<int>();

            foreach (var polygon in csg.Polygons)
            {
                var polygonVertices = new double[0];
                var polygonIndices = new int[0];

                switch (polygon.Vertices.Count)
                {
                    case 3:
                        polygonVertices = CreateTriangle(polygon, out polygonIndices, vertices.Count / 3);
                        break;
                    case 4:
                        polygonVertices = CreateRectangle(polygon, out polygonIndices, vertices.Count / 3);
                        break;
                    case 5:
                        polygonVertices = CreatePentagon(polygon, out polygonIndices, vertices.Count / 3);
                        break;
                    case 6:
                        polygonVertices = CreateHexagon(polygon, out polygonIndices, vertices.Count / 3);
                        break;
                    default:
                        polygonVertices = CreatePolygon(polygon, out polygonIndices, vertices.Count / 3);
                        break;
                }

                vertices.AddRange(polygonVertices);
                indices.AddRange(polygonIndices);
            }

            var posAttr = new Float32BufferAttribute(vertices.ToArray(), 3);
            geometry.setAttribute("position", posAttr);
            geometry.setIndex(indices.ToArray());
            geometry.computeVertexNormals();
            return geometry;
        }

        private double[] CreatePolygon(CsgPolygon polygon, out int[] indices, int indexId)
        {
            double[] vertices = new double[polygon.Vertices.Count * 3];
            for (var i = 0; i < polygon.Vertices.Count; i++)
            {
                vertices[i * 3 + 0] = polygon.Vertices[i].Pos.X;
                vertices[i * 3 + 1] = polygon.Vertices[i].Pos.Y;
                vertices[i * 3 + 2] = polygon.Vertices[i].Pos.Z;
            }


            var vert0 = polygon.Vertices[0];
            var vert1 = polygon.Vertices[1];
            var vert2 = polygon.Vertices[2];
            var v0 = new Vec3(vert0.Pos.X, vert0.Pos.Y, vert0.Pos.Z);
            var v1 = new Vec3(vert1.Pos.X, vert1.Pos.Y, vert1.Pos.Z);
            var v2 = new Vec3(vert2.Pos.X, vert2.Pos.Y, vert2.Pos.Z);

            Vec3 normal = Vec3.cross(v1 - v0, v2 - v0);
            int normdim = Vec3.abs(normal.clone()).maxDim();
            int dim0 = (normdim + 1) % 3;
            int dim1 = (normdim + 2) % 3;
            double sign_flip = (normal[normdim] < 0.0) ? -1.0 : 1.0;

            var vertics = new ListEx<Vector2>();
            for (var i = 0; i < polygon.Vertices.Count; i++)
            {
                var p = polygon.Vertices[i];
                vertics.Add(new Vector2(GetDim(p, dim0), GetDim(p, dim1) * sign_flip));
            }

            var result = ShapeUtils.triangulateShape(vertics, new ListEx<ListEx<Vector2>>());
            indices = new int[result.Count * 3];
            for (var i = 0; i < result.Count; i++)
            {
                var tri = result[i];
                indices[i * 3 + 0] = (indexId + tri[0]);
                indices[i * 3 + 1] = (indexId + tri[1]);
                indices[i * 3 + 2] = (indexId + tri[2]);
            }

            return vertices;
        }
        private double GetDim(CsgVertex v, int dim)
        {
            if (dim == 0) return v.Pos.X;
            else if (dim == 1) return v.Pos.Y;
            else return v.Pos.Z;
        }
        private double[] CreateTriangle(CsgPolygon polygon, out int[] indices, int indexId)
        {
            double[] vertices = new double[9];
            indices = new int[3];
            for (var i = 0; i < 3; i++)
            {
                vertices[i * 3 + 0] = polygon.Vertices[i].Pos.X;
                vertices[i * 3 + 1] = polygon.Vertices[i].Pos.Y;
                vertices[i * 3 + 2] = polygon.Vertices[i].Pos.Z;
            }
            indices[0] = (indexId + 0);
            indices[1] = (indexId + 1);
            indices[2] = (indexId + 2);
            return vertices;
        }

        private double[] CreateRectangle(CsgPolygon polygon, out int[] indices, int indexId)
        {
            double[] vertices = new double[12];
            indices = new int[6];
            for (var i = 0; i < 4; i++)
            {
                vertices[i * 3 + 0] = polygon.Vertices[i].Pos.X;
                vertices[i * 3 + 1] = polygon.Vertices[i].Pos.Y;
                vertices[i * 3 + 2] = polygon.Vertices[i].Pos.Z;
            }

            indices[0] = (indexId + 0);
            indices[1] = (indexId + 1);
            indices[2] = (indexId + 2);
            indices[3] = (indexId + 0);
            indices[4] = (indexId + 2);
            indices[5] = (indexId + 3);

            return vertices;
        }

        private double[] CreatePentagon(CsgPolygon polygon, out int[] indices, int indexId)
        {
            double[] vertices = new double[15];
            indices = new int[9];

            for (var i = 0; i < 5; i++)
            {
                vertices[i * 3 + 0] = polygon.Vertices[i].Pos.X;
                vertices[i * 3 + 1] = polygon.Vertices[i].Pos.Y;
                vertices[i * 3 + 2] = polygon.Vertices[i].Pos.Z;
            }

            indices[0] = (indexId + 0);
            indices[1] = (indexId + 1);
            indices[2] = (indexId + 2);
            indices[3] = (indexId + 0);
            indices[4] = (indexId + 2);
            indices[5] = (indexId + 3);
            indices[6] = (indexId + 0);
            indices[7] = (indexId + 3);
            indices[8] = (indexId + 4);

            return vertices;
        }

        private double[] CreateHexagon(CsgPolygon polygon, out int[] indices, int indexId)
        {
            double[] vertices = new double[18];
            indices = new int[12];

            for (var i = 0; i < 6; i++)
            {
                vertices[i * 3 + 0] = polygon.Vertices[i].Pos.X;
                vertices[i * 3 + 1] = polygon.Vertices[i].Pos.Y;
                vertices[i * 3 + 2] = polygon.Vertices[i].Pos.Z;
            }

            indices[0] = (short)(indexId + 0);
            indices[1] = (short)(indexId + 1);
            indices[2] = (short)(indexId + 2);
            indices[3] = (short)(indexId + 0);
            indices[4] = (short)(indexId + 2);
            indices[5] = (short)(indexId + 3);
            indices[6] = (short)(indexId + 0);
            indices[7] = (short)(indexId + 3);
            indices[8] = (short)(indexId + 4);
            indices[9] = (short)(indexId + 0);
            indices[10] = (short)(indexId + 4);
            indices[11] = (short)(indexId + 5);

            return vertices;
        }



        private void chkWireframe_CheckedChanged(object sender, EventArgs e)
        {
            materialA.wireframe = !materialA.wireframe;
            materialB.wireframe = !materialB.wireframe;
            matResult.wireframe = !matResult.wireframe;
        }

        private void btnDir_Click(object sender, EventArgs e)
        {
            if (this.geometryB == null) return;

            this.model.clear();
            var meshA = new Mesh(this.geometryA, this.materialA);
            var meshB = new Mesh(this.geometryB, this.materialB);
            this.model.add(meshA);
            this.model.add(meshB);

            var name = (sender as Button).Name;
            var transMatrix = new Matrix4();
            switch (name)
            {
                case "btnUp":
                    transMatrix.MakeTranslation(0, 10, 0);
                    break;
                case "btnDown":
                    transMatrix.MakeTranslation(0, -10, 0);
                    break;
                case "btnLeft":
                    transMatrix.MakeTranslation(-10, 0, 0);
                    break;
                case "btnRight":
                    transMatrix.MakeTranslation(10, 0, 0);
                    break;
                case "btnFront":
                    transMatrix.MakeTranslation(0, 0, 10);
                    break;
                case "btnBack":
                    transMatrix.MakeTranslation(0, 0, -10);
                    break;
            }
            this.geometryB.applyMatrix4(transMatrix);


        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            curActionButton = null;
            cboGeo_SelectedIndexChanged(null, null);
        }
    }
}
